<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting in QtJambi</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, painting  QtJambi, Java">
<meta name="description" content="Painting in QtJambi">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting in QtJambi</h1>

<p>
In this part of the QtJambi programming tutorial we will do some painting. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 

<p>
When do we need to paint? There are situations, when we need to create a 
widget from scratch. In such a case, we
need to do painting. Or we want to create charts, special ornaments, 
effects or widget enhancements.  
</p>

<p>
The <b class="keyword">QPainter</b> class is instrumental when we do some 
painting in the QtJambi library. Paint events are received in the 
<b class="keyword">paintEvent()</b> method. To do custom painting, we must reimplement
this method. 
</p>


<h2>Patterns</h2>

<p>
In QtJambi, there are various patterns, that we can use to fill the interiors of shapes. 
</p>

<pre class="code">
package com.zetcode;

import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPen;
import com.trolltech.qt.gui.QWidget;

/**
 * ZetCode QtJambi tutorial
 *
 * This program draws nine rectangles.
 * The interiors are filled with
 * different built-in patterns.
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class JambiApp extends QWidget {
    
    public JambiApp() {
        
        setWindowTitle("Patterns");

        resize(350, 280);
        move(400, 300);
        show();
    }

    @Override
    protected void paintEvent(QPaintEvent event) {

        QPainter painter = new QPainter(this);
        drawPatterns(painter);
    }

    private void drawPatterns(QPainter painter) {

          painter.setPen(QPen.NoPen);

          painter.setBrush(Qt.BrushStyle.HorPattern);
          painter.drawRect(10, 15, 90, 60);

          painter.setBrush(Qt.BrushStyle.VerPattern);
          painter.drawRect(130, 15, 90, 60);

          painter.setBrush(Qt.BrushStyle.CrossPattern);
          painter.drawRect(250, 15, 90, 60);

          painter.setBrush(Qt.BrushStyle.Dense7Pattern);
          painter.drawRect(10, 105, 90, 60);

          painter.setBrush(Qt.BrushStyle.Dense6Pattern);
          painter.drawRect(130, 105, 90, 60);

          painter.setBrush(Qt.BrushStyle.Dense5Pattern);
          painter.drawRect(250, 105, 90, 60);

          painter.setBrush(Qt.BrushStyle.BDiagPattern);
          painter.drawRect(10, 195, 90, 60);

          painter.setBrush(Qt.BrushStyle.FDiagPattern);
          painter.drawRect(130, 195, 90, 60);

          painter.setBrush(Qt.BrushStyle.DiagCrossPattern);
          painter.drawRect(250, 195, 90, 60);

          painter.end();
    }
    
    
    public static void main(String[] args) {
        QApplication.initialize(args);
        new JambiApp();
        QApplication.exec();
    }
}
</pre>

<p>
In the code example, we will draw nine rectangles and fill them with
different brush patterns. 
</p>


<pre class="explanation">
@Override
protected void paintEvent(QPaintEvent event) {

    QPainter painter = new QPainter(this);
    drawPatterns(painter);
}
</pre>

<p>
When the window area needs to be redrawn, the <b class="keyword">paintEvent()</b> method
is called. This happens, when we resize the window, maximize it or minimize it etc. 
Inside this method, we create the <b class="keyword">QPainter</b> object. This object is used
to do all painting in QtJambi. The painting itself is delegated to the 
<b class="keyword">drawPatterns()</b> method.
</p>

<pre class="explanation">
painter.setPen(QPen.NoPen);
</pre>

<p>
The pen object is used to draw outlines of the shapes. In our example
we will not use a pen. 
</p>

<pre class="explanation">
painter.setBrush(Qt.BrushStyle.HorPattern);
</pre>

<p>
We set a horizontal pattern as a brush. 
</p>

<pre class="explanation">
painter.drawRect(10, 15, 90, 60);
</pre>

<p>
We draw a rectangle, with the current pen and brush.
The first two parameters of the method are the x, y coordinates.
The last two parameters are the width and height of the rectangle. 
</p>

<pre class="explanation">
painter.end();
</pre>

<p>
Ends painting. Any resources used while painting are released. 
According to the documentation, this call is not necessary in QtJambi. 
The resources are freed by the destructor. 
</p>

<br>
<img src="/img/gui/qtjambi/patterns.png" alt="Patterns">
<div class="figure">Figure: Patterns</div>



<h2>Shapes</h2>

<p>
The QtJambi painting API can draw various shapes. The following programming code example will show some of them. 
</p>

<pre class="code">
package com.zetcode;

import com.trolltech.qt.core.QPoint;
import com.trolltech.qt.core.QPointF;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QBrush;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QFont;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPainterPath;
import com.trolltech.qt.gui.QPen;
import com.trolltech.qt.gui.QPolygon;
import com.trolltech.qt.gui.QWidget;
import java.util.ArrayList;
import java.util.List;

/**
 * ZetCode QtJambi tutorial
 *
 * This program draws basic shapes
 * available in QtJambi
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class JambiApp extends QWidget {
    
    public JambiApp() {
        
        setWindowTitle("Shapes");

        resize(350, 280);
        move(400, 300);
        show();
    }

    @Override
    protected void paintEvent(QPaintEvent event) {

        QPainter painter = new QPainter(this);
        drawShapes(painter);
    }

    private void drawShapes(QPainter painter) {

        painter.setRenderHint(QPainter.RenderHint.Antialiasing);
        painter.setPen(new QPen(new QBrush(QColor.darkGray), 1));
        painter.setBrush(QColor.darkGray);

        QPainterPath path1 = new QPainterPath();

        path1.moveTo(5, 5);
        path1.cubicTo(40, 5,  50, 50,  99, 99);
        path1.cubicTo(5, 99,  50, 50,  5, 5);
        painter.drawPath(path1);

        painter.drawPie(130, 20, 90, 60, 30*16, 120*16);
        painter.drawChord(240, 30, 90, 60, 0, 16*180);
        painter.drawRoundRect(20, 120, 80, 50);

        List<QPoint> points = new ArrayList<QPoint>();
        points.add(new QPoint(130, 140));
        points.add(new QPoint(180, 170));
        points.add(new QPoint(180, 140));
        points.add(new QPoint(220, 110));
        points.add(new QPoint(140, 100));

        QPolygon polygon = new QPolygon(points);

        painter.drawPolygon(polygon);
        painter.drawRect(250, 110, 60, 60);

        QPointF baseline = new QPointF(20, 250);
        QFont font = new QFont("Georgia", 55);
        QPainterPath path2 = new QPainterPath();
        path2.addText(baseline, font, "Q");
        painter.drawPath(path2);

        painter.drawEllipse(140, 200, 60, 60);
        painter.drawEllipse(240, 200, 90, 60);
    }
    
    
    public static void main(String[] args) {
        QApplication.initialize(args);
        new JambiApp();
        QApplication.exec();
    }
}
</pre>

<p>
In this code example, we draw nine different shapes on the window. A complex path, 
a pie, a chord, a rounded rectangle, a polygon, a rectangle, a character based shape,
a circle and an ellipse. 
</p>


<pre class="explanation">
painter.setRenderHint(QPainter.RenderHint.Antialiasing);
</pre>

<p>
We use antialiasing in the example. Antialiased shapes look better, but it takes more 
time to draw them. 
</p>

<pre class="explanation">
painter.setPen(new QPen(new QBrush(QColor.darkGray), 1));
painter.setBrush(QColor.darkGray);
</pre>

<p>
We use a dark gray pen and brush to draw the shapes. 
</p>

<pre class="explanation">
QPainterPath path1 = new QPainterPath();

path1.moveTo(5, 5);
path1.cubicTo(40, 5,  50, 50,  99, 99);
path1.cubicTo(5, 99,  50, 50,  5, 5);
painter.drawPath(path1);
</pre>

<p>
The first complex shape is created with the <b class="keyword">QPainterPath</b> object. 
The QPainterPath class provides a container for painting operations. A painter path is an 
object composed of a number of graphical building blocks, such as rectangles, ellipses, lines, and curves.
</p>

<pre class="explanation">
painter.drawPie(130, 20, 90, 60, 30*16, 120*16);
painter.drawChord(240, 30, 90, 60, 0, 16*180);
painter.drawRoundRect(20, 120, 80, 50);
</pre>

<p>
These three lines draw a pie, a chord and a rounded rectangle. 
</p>

<pre class="explanation">
List<QPoint> points = new ArrayList<QPoint>();
points.add(new QPoint(130, 140));
points.add(new QPoint(180, 170));
points.add(new QPoint(180, 140));
points.add(new QPoint(220, 110));
points.add(new QPoint(140, 100));

QPolygon polygon = new QPolygon(points);

painter.drawPolygon(polygon);
</pre>

<p>
We use a list of five points to create a polygon. 
</p>

<pre class="explanation">
QPointF baseline = new QPointF(20, 250);
QFont font = new QFont("Georgia", 55);
QPainterPath path2 = new QPainterPath();
path2.addText(baseline, font, "Q");
painter.drawPath(path2);
</pre>

<p>
These lines create a character based shape. 
</p>

<pre class="explanation">
painter.drawEllipse(140, 200, 60, 60);
painter.drawEllipse(240, 200, 90, 60);
</pre>

<p>
These two lines create a circle and an ellipse respectively.
</p>

<br>
<img src="/img/gui/qtjambi/shapes.png" alt="Shapes">
<div class="figure">Figure: Shapes</div>



<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material.
The easiest way to understand transparency is to imagine a piece of
glass or water. Technically, the rays of light can go through the 
glass and this way we can see objects behind the glass.
</p>

<p>
In computer graphics, we can achieve transparency effects using alpha compositing.
 Alpha compositing is the process of combining an image with a background 
to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com) 
</p>

<pre class="code">
package com.zetcode;

import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPen;
import com.trolltech.qt.gui.QWidget;

/**
 * ZetCode QtJambi tutorial
 *
 * This program draws ten
 * rectangles with different
 * levels of transparency
 * 
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class JambiApp extends QWidget {
    
    public JambiApp() {
        
        setWindowTitle("Transparent rectangles");

        resize(590, 90);
        move(400, 300);
        show();
    }

    @Override
    protected void paintEvent(QPaintEvent event) {

        QPainter painter = new QPainter(this);
        drawRectangles(painter);

    }

    private void drawRectangles(QPainter painter) {

        painter.setPen(QPen.NoPen);

        for (int i=1; i<11; i++) {
            painter.setBrush(new QColor(0, 0, 255, i*25));
            painter.drawRect(50*i, 20, 40, 40);
        }
    }
    
    
    public static void main(String[] args) {
        QApplication.initialize(args);
        new JambiApp();
        QApplication.exec();
    }
}
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>


<pre class="explanation">
painter.setPen(QPen.NoPen);
</pre>

<p>
We use no pen. 
</p>

<pre class="explanation">
for (int i=1; i<11; i++) {
    painter.setBrush(new QColor(0, 0, 255, i*25));
    painter.drawRect(50*i, 20, 40, 40);
}
</pre>

<p>
The last parameter of the QColor object is the alpha transparency value. 
</p>


<br>
<img src="/img/gui/qtjambi/trect.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>


<h2>Donut Shape</h2>

<p>
In the following example we create a complex shape by rotating a bunch of ellipses. 
</p>

<pre class="code">
package com.zetcode;

import com.trolltech.qt.core.QPoint;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPen;
import com.trolltech.qt.gui.QWidget;

/**
 * ZetCode QtJambi tutorial
 *
 * This program draws a donut
 * shape
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */


public class JambiApp extends QWidget {
    
    public JambiApp() {
        
        setWindowTitle("Donut");

        resize(350, 280);
        move(400, 300);
        show();
    }

    @Override
    protected void paintEvent(QPaintEvent event) {

        QPainter painter = new QPainter(this);
        drawDonut(painter);

    }

    private void drawDonut(QPainter painter) {

        QColor color = new QColor();
        color.setNamedColor("#333333");

        painter.setPen(new QPen(color, 0.5));

        painter.setRenderHint(QPainter.RenderHint.Antialiasing);

        int w = width();
        int h = height();

        painter.translate(new QPoint(w/2, h/2));

         for (double rot=0; rot < 360.0; rot+=5.0 ) {
             painter.drawEllipse(-125, -40, 250, 80);
             painter.rotate(5.0);
         }
    }

    
    public static void main(String[] args) {
        QApplication.initialize(args);
        new JambiApp();
        QApplication.exec();
    }
}
</pre>

<p>
In this example, we create a donut. The shape resembles a cookie, hence the name donut. 
</p>


<pre class="explanation">
QColor color = new QColor();
color.setNamedColor("#333333");
</pre>

<p>
We can use a hexadecimal notation to create a color object. 
</p>

<pre class="explanation">
int w = width();
int h = height();
</pre>

<p>
Here we determine the width and height of the window. 
</p>

<pre class="explanation">
painter.translate(new QPoint(w/2, h/2));
</pre>

<p>
We move the coordinate system to the middle of the window. This way we
make the drawing mathematically easier. 
</p>

<pre class="explanation">
for (double rot=0; rot < 360.0; rot+=5.0 ) {
    painter.drawEllipse(-125, -40, 250, 80);
    painter.rotate(5.0);
}
</pre>

<p>
We draw an ellipse object 72 times. Each time, we rotate the
ellipse by 5 degrees. This will create our donut shape.
</p>


<br>
<img src="/img/gui/qtjambi/donut.png" alt="Donut">
<div class="figure">Figure: Donut</div>



<h2>Drawing text</h2>

<p>
In the last example, we are going to draw text
on the window. 
</p>

<pre class="code">
package com.zetcode;

import com.trolltech.qt.core.QPoint;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QFont;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QWidget;

/**
 * ZetCode QtJambi tutorial
 *
 * This program draws text
 * on the window
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class JambiApp extends QWidget {
    
    public JambiApp() {
        
        setWindowTitle("Soulmate");

        resize(370, 240);
        move(400, 300);
        show();
    }

    @Override
    protected void paintEvent(QPaintEvent event) {

        QPainter painter = new QPainter(this);
        drawLyrics(painter);

    }

    private void drawLyrics(QPainter painter) {

        painter.setBrush(new QColor(25, 25, 25));
        painter.setFont(new QFont("Purisa", 10));

        painter.drawText(new QPoint(20, 30),
                "Most relationships seem so transitory");
        painter.drawText(new QPoint(20, 60),
                "They're good but not the permanent one");
        painter.drawText(new QPoint(20, 120),
                "Who doesn't long for someone to hold");
        painter.drawText(new QPoint(20, 150),
                "Who knows how to love without being told");
        painter.drawText(new QPoint(20, 180),
                "Somebody tell me why I'm on my own");
        painter.drawText(new QPoint(20, 210),
                "If there's a soulmate for everyone");
    }
    
    
    public static void main(String[] args) {
        QApplication.initialize(args);
        new JambiApp();
        QApplication.exec();
    }
}
</pre>

<p>
We draw a song lyrics on the window. 
</p>

<pre class="explanation">
painter.setFont(new QFont("Purisa", 10));
</pre>

<p>
We set a Purisa font for our text. 
</p>

<pre class="explanation">
painter.drawText(new QPoint(20, 30),
        "Most relationships seem so transitory");
</pre>

<p>
The <b class="keyword">drawText()</b> method is used
to draw the text. 
</p>


<br>
<img src="/img/gui/qtjambi/soulmate.png" alt="Drawing text">
<div class="figure">Figure: Drawing text</div>

<hr class="btm">

<p>
In this part of the QtJambi programming tutorial, we did some
painting.
</p>

<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified April 27, 2009  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body> 
</html>
